/** biome-ignore-all lint/suspicious/noExplicitAny: off */
import type { Middleware, TypedKey } from './types';
import { assertTypedKey, isMiddleware } from './types';

export class Context {
  protected data: Record<string, unknown>;
  protected listeners: Record<string, Array<{
    listener: (newValue: unknown) => void;
    condition?: (newValue: unknown, oldValue: unknown) => boolean;
  } | ((newValue: unknown) => void)>> = {};
  protected batchUpdates: Map<string, unknown> = new Map();
  protected isBatching = false;
  protected middleware: Middleware[] = [];

  constructor(
    initialValue: Record<string, unknown> = {},
    middleware: Middleware[] = [],
  ) {
    this.data = { ...initialValue };
    this.middleware = middleware.filter(isMiddleware);
  }

  // 添加中间件
  addMiddleware(...newMiddleware: Middleware[]): void {
    this.middleware.push(...newMiddleware.filter(isMiddleware));
  }

  // 移除中间件
  removeMiddleware(middlewareToRemove: Middleware): void {
    this.middleware = this.middleware.filter((m) => m !== middlewareToRemove);
  }

  // 清除所有中间件
  clearMiddleware(): void {
    this.middleware = [];
  }

  getData<T>(key: TypedKey<T>): T {
    // 验证输入参数类型
    assertTypedKey(key);

    if (!(key.key in this.data)) {
      this.data[key.key] = key.defaultValue;
    }
    return this.data[key.key] as T;
  }

  setData<T>(key: TypedKey<T>, value: T, immediate = true): void {
    // 验证输入参数类型
    assertTypedKey(key);

    // 中间件处理逻辑
    const processMiddleware = (
      currentValue: unknown,
      middlewareIndex: number,
    ) => {
      if (middlewareIndex >= this.middleware.length) {
        // 所有中间件执行完成，设置最终值
        if (immediate) {
          this.data[key.key] = currentValue;
          this.notifyListeners(key.key, currentValue);
        } else {
          this.batchUpdates.set(key.key, currentValue);

          if (!this.isBatching) {
            this.flushBatchUpdates();
          }
        }
        return;
      }

      // 执行当前中间件
      const middleware = this.middleware[middlewareIndex];
      middleware(key.key, currentValue, (nextValue) => {
        // 调用下一个中间件
        processMiddleware(nextValue, middlewareIndex + 1);
      });
    };

    // 开始执行中间件链
    processMiddleware(value, 0);
  }

  subscribe<T>(
    key: TypedKey<T>,
    listener: (newValue: T) => void,
    condition?: (newValue: T, oldValue: T) => boolean,
  ): () => void {
    // 验证输入参数类型
    assertTypedKey(key);

    const keyStr = key.key;
    if (!this.listeners[keyStr]) {
      this.listeners[keyStr] = [];
    }

    // 保存订阅者信息，包括回调和条件函数
    const subscription = {
      listener: listener as (newValue: unknown) => void,
      condition: condition as
        | ((newValue: unknown, oldValue: unknown) => boolean)
        | undefined,
    };

    this.listeners[keyStr].push(
      subscription as unknown as (newValue: unknown) => void,
    );

    return () => {
      const index = this.listeners[keyStr].findIndex(
        (sub) => (sub as any).listener === subscription.listener,
      );
      if (index > -1) {
        this.listeners[keyStr].splice(index, 1);
      }
    };
  }

  batch(callback: () => void): void {
    const prevBatching = this.isBatching;
    this.isBatching = true;

    try {
      callback();
    } finally {
      this.isBatching = prevBatching;
      if (!this.isBatching) {
        this.flushBatchUpdates();
      }
    }
  }

  protected flushBatchUpdates(): void {
    if (this.batchUpdates.size === 0) return;

    // 使用React的批量更新API，如果可用
    const batchedUpdates =
      (require('react-dom') as any)
        .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
        ?.unstable_batchedUpdates || ((fn: () => void) => fn());

    batchedUpdates(() => {
      this.batchUpdates.forEach((value, key) => {
        this.data[key] = value;
        this.notifyListeners(key, value);
      });
      this.batchUpdates.clear();
    });
  }

  protected notifyListeners(key: string, newValue: unknown): void {
    // 处理特定键的订阅者
    if (this.listeners[key]) {
      const oldValue = this.data[key];

      // 使用切片复制数组，避免在遍历过程中修改数组
      this.listeners[key].slice().forEach((subscription) => {
        try {
          // 检查订阅者是对象还是函数
          if (typeof subscription === 'object' && subscription !== null && 'listener' in subscription) {
            // 订阅者是对象类型，有listener和condition属性
            const sub = subscription as { listener: (newValue: unknown) => void; condition?: (newValue: unknown, oldValue: unknown) => boolean };
            // 如果有条件函数，检查是否满足条件
            if (
              !sub.condition ||
              sub.condition(newValue, oldValue)
            ) {
              sub.listener(newValue);
            }
          } else if (typeof subscription === 'function') {
            // 兼容旧版订阅者
            subscription(newValue);
          }
        } catch (error) {
          console.error(`Error in listener for key ${key}:`, error);
        }
      });
    }

    // 处理'*'键的订阅者（监听所有变化）
    if (key !== '*' && this.listeners['*']) {
      // 使用切片复制数组，避免在遍历过程中修改数组
      this.listeners['*'].slice().forEach((subscription) => {
        try {
          // 检查订阅者是对象还是函数
          if (typeof subscription === 'object' && subscription !== null && 'listener' in subscription) {
            // 订阅者是对象类型，有listener和condition属性
            const sub = subscription as { listener: (newValue: unknown) => void; condition?: (newValue: unknown, oldValue: unknown) => boolean };
            // 对于'*'键的订阅者，newValue是整个状态
            const state = { ...this.data };
            sub.listener(state);
          } else if (typeof subscription === 'function') {
            // 兼容旧版订阅者
            const state = { ...this.data };
            subscription(state);
          }
        } catch (error) {
          console.error('Error in listener for key *:', error);
        }
      });
    }
  }

  // 工具方法
  getAllData(): Record<string, unknown> {
    return { ...this.data };
  }

  clear(): void {
    this.data = {};
    this.batchUpdates.clear();
    Object.keys(this.listeners).forEach((key) => {
      this.listeners[key] = [];
    });
  }

  // 订阅者管理
  getSubscriptionCount(key?: string): number {
    if (key) {
      return this.listeners[key]?.length || 0;
    }
    return Object.values(this.listeners).reduce(
      (total, listeners) => total + listeners.length,
      0,
    );
  }

  clearSubscriptions(key?: string): void {
    if (key) {
      this.listeners[key] = [];
    } else {
      this.listeners = {};
    }
  }

  // 添加useSyncExternalStore支持
  useSyncExternalStore<T>(
    key: TypedKey<T>,
    _equalityFn: (a: T, b: T) => boolean,
  ) {
    // 这个方法会被useListen钩子调用，用于React 18的useSyncExternalStore
    return this.getData(key);
  }
}
